const {
    JSDOM
} = require('jsdom');
const {
    parseRating
} = require('./toolkit');
const CronJob = require("cron").CronJob;
const gather = require('./gather');
const MassPromise = require('../base/MassPromise');

function schedule() {
    new CronJob('0 0,30 * * * *', updateAll);
}

async function updateAll() {
    console.log(`update all raised...${Date()}`);
    let codes = 
    [
        'BA', 'MA', 'ADI', 'AVGO', 'V', 'RHT', 'PGR', 'TXN', 
        'TAL', 'RTN', 'ASML', 'AMAT', 'CTRP', 'BABA', 'BFAM', 
        'UNH', 'FB', 'PYPL', 'JD', 'ATVI', 'INTC', 'TSM', 
        'NVDA', 'TAL', 'EDU', 'MSFT', 'GOOG', 'AMD', 
        'BIDU', 'CVX', 'BBY', 'NEE', 'NICE', 'OLED', 
        'XEL', 'AON', 'CI', 'EL', 'AXP', 'JPM', 'HII', 'CAT', 
        'ACN', 'NOC', 'MS', 'STMP', 'LOPE', 'IBKR', 'ISRG',
        'ILMN', 'TSS', 'ANSS', 'SYY', 'ECL', 'AMED', 'ENTA',
        'CNC', 'RLI', 'BRK.B', 'BSX', 'MDT', 'ABT', 'COP',
        'WMT', 'MRK'
    ];
    let stocks = [];
    let massPromise = MassPromise();
    for (let code of codes) {
        let promise = fetch({ code, source: 'thestreet' })
            .then(({ level, action }) => {
                if (!level || !action) {
                    return;
                }
                stocks[code] = `${level} (${action})`;
            }).catch(err => console.error('error@' + code + ':' + err.message));
        massPromise.addTask(promise);
        console.log(`fetch task fired...${code}`);
        await waitFor(2500);
    }
    massPromise
        .awaitAll()
        .then(() => {
            console.log('MassPromise.completed');
            return gather.update({ stocks, updateAt: Date(), source: 'thestreet' });
        }).catch(err => console.error('error@2', JSON.stringify(err)));
}

const waitFor = async ms => new Promise(resolve => setTimeout(resolve, ms));

function fetch({ code, source, retryTimes = 0 }) {
    const beginAt = Date.now();
    const fetchPromise = JSDOM.fromURL(`https://www.thestreet.com/quote/${code}`, {
        referrer: "https://www.thestreet.com/",
        userAgent: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
    });
    return Promise
    .race([waitFor(10000), fetchPromise])
    .then(dom => {
        if (!dom) {
            throw Error(`spider timeout for ${code} and a retry would be operate.`);
        }
        var $ = require('jquery')(dom.window);
        var elmts = $.find('#promo-div-quote-nav-unit-small-screen > div.quote-nav-rating-qr-label-container');
        if (elmts.length == 0) {
            console.error(`no targets found in page of code=${code}!`);
            return {};
        }
        let ratingValue = elmts[0].childNodes[3].textContent;
        let { level, action } = parseRating(ratingValue);
        console.log(`rating found in page of code=${code}...${level} (${action}), cost...${Date.now() - beginAt}ms`);
        return {
            StockCode: code,
            level,
            action,
            type: 'thestreet',
            date: Date()
        }
    }).catch(err => {
        if (retryTimes >= 2) {
            throw err;
        }
        retryTimes += 1;
        console.log(`fetch error...${err.message} after ${Date.now() - beginAt}ms, retrying for ${code} of ${retryTimes} times`);
        return fetch({ code, source, retryTimes });
    });
}

module.exports = {
    fetch,
    schedule
};

updateAll();